from rest_framework.response import Response
from rest_framework.throttling import AnonRateThrottle, UserRateThrottle
from rest_framework import filters
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.generics import ListAPIView, GenericAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, \
    CreateModelMixin
from rest_framework.pagination import PageNumberPagination
from rest_framework import viewsets
# import jieba
from .models import Product, GoodCategory, Good, IndexCarouselGood, HotSearchWords, Attribute, SPG, Param
from .serializers import ProductSerializer, GoodCategorySerializer, CarouselGoodSerializer, CategoryBrandAdSerializer, \
    HotSearchSerializer, IndexFilterGoodSerializer, GoodSerializer, ProductSerializerOne, AttributeSerializer, \
    SpgSerializer, SpgAttributeSerializer, ParamSerializer, CreateProductSerializer, UpdateProductSerializer
from .filters import GoodsFilter, ProductFilter
from .train import main
from rest_framework_extensions.cache.mixins import CacheResponseMixin
from apps.utils.custom_response import CustomPagination


class CategoryBrandViewSet(ListModelMixin, viewsets.GenericViewSet):
    serializer_class = CategoryBrandAdSerializer
    queryset = GoodCategory.objects.filter(is_banner=True).filter(category_type=1)
    pagination_class = CustomPagination


class SPGViewSet(viewsets.GenericViewSet, ListAPIView, CreateModelMixin, DestroyModelMixin, RetrieveModelMixin):
    # serializer_class = SpgSerializer
    queryset = SPG.objects.all()
    pagination_class = CustomPagination

    def get_serializer_class(self):
        if self.action == 'retrieve':
            return SpgAttributeSerializer
        else:
            return SpgSerializer

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        data = {
            'code': 200,
            'message': 'success',
            'data': ''
        }
        return Response(data)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data, status='200', headers=headers)

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data)


class ParamViewSet(viewsets.GenericViewSet, ListAPIView, DestroyModelMixin, CreateModelMixin, UpdateModelMixin,
                   RetrieveModelMixin):
    serializer_class = ParamSerializer
    queryset = Param.objects.all()
    pagination_class = CustomPagination
    filterset_fields = ['apg']

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data)

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data)

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data)


class AttributeViewSet(viewsets.GenericViewSet, ListAPIView, DestroyModelMixin, CreateModelMixin, UpdateModelMixin,
                       RetrieveModelMixin):
    serializer_class = AttributeSerializer
    queryset = Attribute.objects.all()
    pagination_class = CustomPagination
    filterset_fields = ['apg']

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data)

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data)

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data)


class GoodCategoryBrandViewSet(ListModelMixin, viewsets.GenericViewSet):
    serializer_class = CarouselGoodSerializer
    queryset = IndexCarouselGood.objects.all()


class HotSearchViewSet(ListModelMixin, viewsets.GenericViewSet):
    """
    获取热搜词列表
    """
    queryset = HotSearchWords.objects.all().order_by("-sort")
    serializer_class = HotSearchSerializer


class GoodPagination(PageNumberPagination):
    page_size = 20
    max_page_size = 100
    page_size_query_param = 'page_size'
    page_query_param = 'page'


# CacheResponseMixin,
class HotProductListViewSet(ListAPIView, viewsets.GenericViewSet):
    throttle_classes = (AnonRateThrottle, UserRateThrottle)
    queryset = Good.objects.filter(is_hot=1)[:5]
    serializer_class = IndexFilterGoodSerializer
    pagination_class = CustomPagination


class GoodListViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, viewsets.GenericViewSet):
    """
    这里注意  商品查询
    """
    throttle_classes = (AnonRateThrottle, UserRateThrottle)
    # serializer_class = GoodSerializer
    queryset = Good.objects.all().order_by('id')
    pagination_class = CustomPagination
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filter_class = GoodsFilter
    ordering_fields = ['sold_num', 'sold_price']

    # 修改主键
    # lookup_field = 'sn'

    def get_serializer_class(self):
        if self.action == 'list':
            return GoodSerializer
        elif self.action == 'partial_update':
            return UpdateProductSerializer
        else:
            return ProductSerializer

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        # word_list = jieba.lcut(str(instance.name))
        # all_good = [x[0] for x in Good.objects.values_list('name')]
        # all_good.remove(str(instance.name))
        # recommend = main(word_list, all_good)
        # instance.click_num += 1
        # instance.save()
        # print(instance)
        serializer = self.get_serializer(instance)
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data)


# CacheResponseMixin,
class ProductListViewSet(UpdateModelMixin, CreateModelMixin, ListAPIView, DestroyModelMixin, RetrieveModelMixin,
                         viewsets.GenericViewSet):
    throttle_classes = (AnonRateThrottle, UserRateThrottle)
    queryset = Product.objects.all().order_by('id')
    # serializer_class = GoodSerializer
    pagination_class = CustomPagination
    # authentication_classes = [JSONWebTokenAuthentication]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    # 产品分为新品 推荐  商品有热卖  目前有销售量算出  以后结合机器学习算出  协同过滤
    filterset_fields = ['is_new', 'is_recommend']  # 精确查找
    filter_class = ProductFilter
    # filters.SearchFilter, filters.OrderingFilter 限制
    # 模糊查询
    search_fields = ['title']

    # 排序
    ordering_fields = ['min_price', 'total_sold']

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data, status=200)
        # return Response(serializer.data)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        # instance.is_de
        self.perform_destroy(instance)
        data = {
            'code': 200,
            'message': 'success',
            'data': ''
        }
        return Response(data, status=200)
        # return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        instance.is_delete = 1
        instance.save()
        # instance.delete()

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data, status=200, headers=headers)
        # return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def get_serializer_class(self):
        print(self.action)
        # update
        if self.action == 'list':
            return IndexFilterGoodSerializer
        elif self.action == 'create':
            return CreateProductSerializer
        elif self.action == 'partial_update':
            return UpdateProductSerializer
        else:
            return ProductSerializerOne

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        # word_list = jieba.lcut(str(instance.name))
        # all_good = [x[0] for x in Good.objects.values_list('name')]
        # all_good.remove(str(instance.name))
        # recommend = main(word_list, all_good)
        # instance.click_num += 1
        # instance.save()
        # print(instance)
        serializer = self.get_serializer(instance)
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data)

    # 继承 ListAPIView viewsets.GenericViewSet
    # 需要在 urls.py 配置 注意两种路由的注册方式
    # good_list = GoodList.as_view({
    #     'get': 'list',
    #
    # })
    # path('good_list/', good_list),

    # 继承 ListAPIView
    # queryset = Good.objects.all()
    # serializer_class = GoodSerializer

    # 继承 ListModelMixin, GenericAPIView
    # queryset = Good.objects.all()
    # serializer_class = GoodSerializer
    #
    # def get(self, request, *args, **kwargs):
    #     return self.list(request, *args, **kwargs)
    #
    # def post(self, request, *args, **kwargs):
    #     return self.create(request, *args, **kwargs)

    # 继承 APIView
    # # 查询
    # def get(self, request, format=None):
    #     goods = Good.objects.all()
    #     goods_serializers = GoodSerializer(goods, many=True)
    #     return Response(goods_serializers.data)
    #
    # # 添加
    # def post(self, request, format=None):
    #     good_serializer = GoodSerializer(data=request.data)
    #     if good_serializer.is_valid():
    #         good_serializer.save()
    #         return Response(good_serializer.data, status=status.HTTP_201_CREATED)
    #     return Response(good_serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class GoodCategoryViewSet(ListAPIView, RetrieveModelMixin, viewsets.GenericViewSet):
    queryset = GoodCategory.objects.filter(category_type=1).order_by('id')
    serializer_class = GoodCategorySerializer
    pagination_class = CustomPagination
